﻿using EnetaMvc.Core.Domain.News;
using EnetaMvc.Core.Repositories;
using EnetaMvc.Infrastructure;
using NHibernate;
using NHibernate.Criterion;

namespace EnetaMvc.Data.NHibernate.Repositories
{
    public class BlogPostRepository : BaseRepository, IBlogPostRepository
    {
        private readonly ISession _session;

        public BlogPostRepository(IMapperSession session) : base(((NHSession)session).GetCurrentSession())
        {
            _session = ((NHSession)session).GetCurrentSession();
        }

        public PagedResult<BlogPost> ListPublishedBlogPosts(int page, int pageSize)
        {
            var criteria = _session.CreateCriteria("BlogPost");
            criteria.CreateCriteria("Blog")
                    .CreateCriteria("PublishingState", "blog_pubstate")
                    .Add(Expression.Eq("IsVisibleOnPublicSite", true));
            criteria.CreateCriteria("PublishState", "blogpost_pubstate")
                    .Add(Expression.Eq("IsVisibleOnPublicSite", true));

            criteria.AddOrder(Order.Desc("Created"));

            return GetPagedResultForQuery<BlogPost>(criteria, page, pageSize);
        }

        public PagedResult<BlogPost> ListBlogPosts(int page, int pageSize)
        {
            var criteria = _session.CreateCriteria<BlogPost>();
            criteria.AddOrder(Order.Desc("Created"));

            return GetPagedResultForQuery<BlogPost>(criteria, page, pageSize);
        }

        public BlogPost GetBlogPostById(long id)
        {
            return _session.Get<BlogPost>(id);
        }

        public BlogPost GetPublishedBlogPost(long id)
        {
            var blogPost = GetBlogPostById(id);
            if (blogPost == null)
                return null;

            if (blogPost.PublishState == null)
                return null;
            if (!blogPost.PublishState.IsVisibleOnPublicSite)
                return null;
            if (blogPost.Blog.PublishingState == null)
                return null;
            if (!blogPost.Blog.PublishingState.IsVisibleOnPublicSite)
                return null;

            return blogPost;
        }

        public void SaveBlogPost(BlogPost blogPost)
        {
            SaveInTransaction(blogPost);
        }

        public PagedResult<BlogPost> ListPublishedPostsForBlog(long blogId, int page, int pageSize)
        {
            var criteria = _session.CreateCriteria<BlogPost>();
                criteria.CreateCriteria("PublishState", "blogpost_pubstate")
                        .Add(Expression.Eq("IsVisibleOnPublicSite", true));

            var blogCriteria = criteria.CreateCriteria("Blog");
                blogCriteria.CreateCriteria("PublishingState", "blog_pubstate")
                            .Add(Expression.Eq("IsVisibleOnPublicSite", true));
                blogCriteria.Add(Expression.Eq("Id", blogId));

            criteria.AddOrder(Order.Desc("Created"));

            return GetPagedResultForQuery<BlogPost>(criteria, page, pageSize);
        }

        public PagedResult<BlogPost> ListPostsForBlog(long blogId, int page, int pageSize)
        {
            var criteria = _session.CreateCriteria<BlogPost>();
            var blogCriteria = criteria.CreateCriteria("Blog");
                blogCriteria.Add(Expression.Eq("Id", blogId));

            criteria.AddOrder(Order.Desc("Created"));

            return GetPagedResultForQuery<BlogPost>(criteria, page, pageSize);
        }


        public bool BlogPostExists(string infoSourceUrl, long blogId)
        {
            var criteria = _session.CreateCriteria<BlogPost>();
                criteria.Add(Expression.Eq("InfoSourceUrl", infoSourceUrl));
            var blogCriteria = criteria.CreateCriteria("Blog");
                blogCriteria.Add(Expression.Eq("Id", blogId));

            return (criteria.SetProjection(Projections.Count("Id")).UniqueResult<int>() > 0);
        }
    }
}
